package com.damai.action.json;

import java.beans.IntrospectionException;
import java.lang.annotation.Annotation;
import java.lang.reflect.Method;
import java.util.ArrayList;
import java.util.List;
import java.util.Map;

import javax.servlet.http.HttpServletRequest;

import com.citywithincity.api.ApiConfig;
import com.citywithincity.reflect.CtClassUtil;
import com.damai.annotation.Param;
import com.jzoom.zoom.aop.reflect.ReflectKit;

import javassist.ClassPool;

public class ParamGetterFactory {
	
	
	public static interface IParamGetterFactory{
		IParamGetter createGetter(Class<?> controller,Method method, String name, Class<?> type, Class<?> paramType);
	}
	
	public static  IParamGetter[] createParamGetter(ClassPool classPool,  Class<?> controllerClass, Method method,IParamGetterFactory factory){
		if(classPool==null){
			classPool = ClassPool.getDefault();
		}
		try{
			String[] names = CtClassUtil.getParams(classPool,  controllerClass,method);
			int index = 0;
			List<IParamGetter> list = new ArrayList<IParamGetter>(names.length);
			for (Class<?> type : method.getParameterTypes()) {
				if(type==List.class){
					list.add(ParamGetterFactory.createGetter( controllerClass,method, names[index++], type,
							
							ReflectKit.getGenericParameterType(method, index, 0)
							,factory));
					
					continue;
				}
				list.add(ParamGetterFactory.createGetter( controllerClass,method, names[index++], type,null,factory));
			}
			IParamGetter[] getters = new IParamGetter[list.size()];
			list.toArray(getters);
			return getters;
		}catch(Exception e){
			
			ApiConfig.error("Create param getter error:" + controllerClass.getName() + " method:" + method.getName(),e);
			throw new RuntimeException(e);
		}
		
	}
	
	public static IParamGetter createGetter(Class<?> controller,Method method, String name, Class<?> type, Class<?> paramType,IParamGetterFactory factory) {
		if(type.isPrimitive()){
			return new SimpleParamGetter(name);
		}else if(type.getName().startsWith("java.lang.")){
			return new SimpleParamGetter(name);
		}else if(type == byte[].class){
			return new SimpleParamGetter(name);
		}else if(type == String[].class){
			return new SimpleParamGetter(name);
		}else if(type == HttpServletRequest.class){
			return new RequestParamGetter();
		}else if(type==Map.class){
			if(name.equals("json")){
				return new JsonParamGetter();
			}else{
				ApiConfig.warn("Param type is Map，but name is not json at " + controller.getName() + ":" + method.getName());
				return new SimpleParamGetter(name);
			}
			
		}else if(type==List.class){
			if(paramType!=null){
				return new ListParamParser(name, paramType);
			}else{
				return new SimpleParamGetter(name);
			}
			
		}else if(factory!=null){
			IParamGetter getter = factory.createGetter(controller, method, name, type, paramType);
			if(getter!=null){
				return getter;
			}
		}
		
		try {
			if(name.equals("json")){
				return new BeanJsonParamGetter(type);
			}else{
				ApiConfig.warn("Param type is Bean，but name is not json at " + controller.getName() + ":" + method.getName());
				return new BeanParamGetter(name,type);
			}
			
		} catch (IntrospectionException e) {
			throw new RuntimeException(e);
		}
	}

}
